package com.tanhua.server.service;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.tanhua.commons.templates.AipFaceTemplate;
import com.tanhua.commons.templates.HuanXinTemplate;
import com.tanhua.commons.templates.OssTemplate;
import com.tanhua.commons.templates.SmsTemplate;
import com.tanhua.domain.db.User;
import com.tanhua.domain.db.UserInfo;
import com.tanhua.domain.mongo.UserLike;
import com.tanhua.domain.vo.ErrorResult;
import com.tanhua.domain.vo.PageResult;
import com.tanhua.domain.vo.UserInfoVo;
import com.tanhua.domain.vo.UserLikeVo;
import com.tanhua.dubbo.api.UserApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.dubbo.api.mongo.FriendApi;
import com.tanhua.dubbo.api.mongo.UserLikeApi;
import com.tanhua.server.interceptor.UserHolder;
import com.tanhua.server.utils.JwtUtils;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.time.Duration;
import java.util.*;

import static javax.swing.UIManager.get;

@Service
public class UserService {

    @Reference
    private UserApi userApi;

    @Autowired
    private SmsTemplate smsTemplate;

    @Autowired(required = false)
    private RedisTemplate<String,String> redisTemplate;

    private static final String  SMS_KEY ="SMS_KEY_";
    private static final String  TOKEN_KEY ="TOKEN_KEY_";

    @Value("${tanhua.secret}")
    private String secret;

    @Reference
    private UserInfoApi userInfoApi;

    //百度人脸识别
    @Autowired
    private AipFaceTemplate aipFaceTemplate;

    //阿里云存储
    @Autowired
    private OssTemplate ossTemplate;

    @Autowired
    private HuanXinTemplate huanXinTemplate;


    @Reference
    private UserLikeApi userLikeApi;

    @Reference
    private FriendApi friendApi;


    @Autowired(required = false)
    private RocketMQTemplate rocketMQTemplate;

    /**
     * 保存用户
     * 参数如果是json格式传递，那么我们接收参数需要添加
     * @return 新增用户的主键
     */
    @PostMapping("/save")
    public ResponseEntity save(@RequestBody User user){
        Long id = userApi.save(user);
        return  ResponseEntity.ok(id);
    }


    /**
     * 根据手机号查找用户
     *
     *
     */
    public ResponseEntity findByMobile(String mobile){
        try {
            User user = userApi.findByMobile(mobile);
            return ResponseEntity.ok(user);
        } catch (Exception e) {
            e.printStackTrace();
            Map<String,String> resultMap = new HashMap<>();
            resultMap.put("errCode","110");
            resultMap.put("errMsg","系统正在升级中，请稍后！");
            return ResponseEntity.status(500).body(resultMap);
        }
    }

    /**
     * 发送验证码短信
     * @param phone  手机号
     * @return
     */
    public ResponseEntity sendSms(String phone) {
        //1. 生成6位验证码  ,为了方便以后的登陆使用，这里的验证码我就写死了。
        String authCode = "123456";//RandomStringUtils.randomNumeric(6);

        //2. 发送到手机号 ,目前由于经费问题，我注释
        System.out.println("验证码是："+ authCode);
//        smsTemplate.sendSms(phone,authCode);


        //3. 把验证码存储到redis中
        String key = SMS_KEY+phone;
        //注意：前端页面其实是一分钟过期的，我们开发阶段是可以搞成时间久一点，5分钟
        redisTemplate.opsForValue().set(key,authCode, Duration.ofMinutes(5)); //设置验证码过期的时间

        //4. 返回响应
        return ResponseEntity.ok(null);

    }

    /**
     * 校验登陆
     * @param phone  手机号
     * @param verificationCode  用户输入的验证码
     * @return
     */
    public ResponseEntity loginVerification(String phone, String verificationCode) {
        //1. 校验验证码
        String key = SMS_KEY+phone;
        String authCode = redisTemplate.opsForValue().get(key);
        if(authCode==null||!authCode.equals(verificationCode)){
            return ResponseEntity.status(401).body(ErrorResult.loginError());
        }
        //2. 删除redis中的验证码
        redisTemplate.delete(key);

        //3.根据手机号查找用户
        User user = userApi.findByMobile(phone);
        //是否为新用户的一个标记
        boolean isNew = false ; //默认不是新用户
        //4. 如果根据手机号查找不到用户，当前用户则为新用户，如果是新用户需要添加保存
        String type="0101"; //默认是登陆行为
        if(user==null){
            user = new User();
            user.setMobile(phone);
            user.setPassword(DigestUtils.md5Hex("123456")); //密码全部都给他123456
//            user.setCreated(new Date());
//            user.setUpdated(new Date());
            long userId = userApi.save(user);
            isNew=true;//是新用户
            user.setId(userId);
            //注册到环信上,否则该用户以后没法收发消息
            huanXinTemplate.register(userId);
            //注册行为
            type="0102";//注册
        }

        //5. 返回响应的信息
        Map<String,Object> resultMap = new HashMap<>();
        //生成token
        String token = JwtUtils.createToken(user.getId(), user.getMobile(), secret);
        //把用户对象存储redis中
        String userJson = JSON.toJSONString(user);
        String tokenKey = TOKEN_KEY+token;
        redisTemplate.opsForValue().set(tokenKey,userJson,Duration.ofHours(4)); //默认4个小时会失效

        //把用户消息发送到rocketmq
        Map<String,Object> param = new HashMap<>();
        param.put("userId",user.getId());
        param.put("type",type);
        param.put("log_time", DateUtil.formatDate(new Date()));
        //把map转换为json
        String mapJson = JSON.toJSONString(param);

        rocketMQTemplate.convertAndSend("tanhua-log",mapJson);



        resultMap.put("token",token);
        resultMap.put("isNew",isNew);
        return ResponseEntity.ok(resultMap);

    }

    /**
     * 保存用户个人详细信息
     * @param userInfo 个人详细信息

     * @return
     */
    public ResponseEntity saveUserInfo(UserInfo userInfo) {
        //1. 根据token查找用户
        User user = UserHolder.get();
        //3. 把user的id赋值一个userInfo的id
        userInfo.setId(user.getId());
        //4.  保存用户的信息
        userInfoApi.save(userInfo);
        //5. 返回响应
        return ResponseEntity.ok(null);
    }

    public User findUserByToken(String token){
        //1. 根据token从redis中取出用户数据
        String tokenKey = TOKEN_KEY+token;
        String userJson = redisTemplate.opsForValue().get(tokenKey);
        if(userJson==null){
            return null;
        }
        //把user的json字符串转换为user的对象
        User user = JSON.parseObject(userJson, User.class);

        //判断用户是否被禁止登录
        String key=1+"_USERSTATUS_"+user.getId();
        String s = redisTemplate.opsForValue().get(key);
        if (s!=null){
           return null;
        }

        return user;
    }

    /**
     * 上传头像
     * @param headPhoto  头像的照片
     * @param token  登陆的标记
     * @return
     */
    public ResponseEntity updateUserHead(MultipartFile headPhoto, String token) throws IOException {
        //1. 根据token查找用户
        User user = findUserByToken(token);
        if(user==null){
            return ResponseEntity.status(401).body(ErrorResult.error());
        }

        //2. 检查是否为人的头像，如果是人的头像，允许使用osstemplate上传
        String picUrl = null;
        if(aipFaceTemplate.detect(headPhoto.getBytes())){ //true代表是人脸
            //上传到阿里云
            picUrl= ossTemplate.upload(headPhoto.getOriginalFilename(), headPhoto.getInputStream());
        }else{

        }

        //3. 把图片的url设置到userInfo中
        UserInfo userInfo = new UserInfo();
        userInfo.setId(user.getId());
        userInfo.setAvatar(picUrl);
        //4. 更新userInfo即可
        userInfoApi.update(userInfo);
        //5. 返回响应
        return ResponseEntity.ok(null);
    }

    /**
     * 读取用户的个人信息
     */
    public ResponseEntity findUserInfoById(Long userID,Long huanxinID) {
        //1. 根据token查找用户
        Long userId = UserHolder.getUserId(); //当前登陆者的用户id
        if(userID!=null){
            userId = userID;
        }else if(huanxinID!=null){
            userId=huanxinID;
        }


        //2. 根据用户的id查找userInfo对象
        UserInfo  userInfo= userInfoApi.findById(userId);


        //3. 创建UserINfoVo对象，把UserInfo对象的数据转移userInfoVo中
        UserInfoVo userInfoVo = new UserInfoVo();
        if(userInfo!=null){
            BeanUtils.copyProperties(userInfo,userInfoVo);//属性名一致，类型一致
            if(userInfo.getAge()!=null){
                userInfoVo.setAge(userInfo.getAge()+"");
            }
        }

        //4. 返回响应即可
        return ResponseEntity.ok(userInfoVo);
    }

    /**
     * 更新用户的个人信息
     * @param userInfo
     * @param token
     * @return
     */
    public ResponseEntity updateUserInfo(UserInfo userInfo, String token) {
        //1. 根据token查找用户
        User user = findUserByToken(token);
        if(user==null){
            return ResponseEntity.status(401).body(ErrorResult.error());
        }
        //2.给UserInfo设置id
        userInfo.setId(user.getId());
        userInfoApi.update(userInfo);
        return ResponseEntity.ok(null);
    }

    /**
     * 统计相互喜欢、喜欢、粉丝数量
     * @return
     */
    public ResponseEntity queryCounts() {
        //1.得到当前登陆者id
        Long userId = UserHolder.getUserId();
        //2. 查询相互相、喜欢、粉丝数量
        Long eachLoveCount = userLikeApi.queryEachLoveCount(userId); //相互喜欢
        Long loveCount = userLikeApi.queryLoveCount(userId); //相互喜欢
        Long fansCount = userLikeApi.queryFansCount(userId); //相互喜欢

        //3. 把统计的数据存储到Map中返回
        Map<String,Long> resultMap = new HashMap<>();
        resultMap.put("eachLoveCount",eachLoveCount);
        resultMap.put("loveCount",loveCount);
        resultMap.put("fanCount",fansCount);

        return ResponseEntity.ok(resultMap);

    }

    public ResponseEntity queryUserLikeList(Integer page, Integer pagesize, String nickname, Integer type) {
        //1. 获取当前的登陆者id
        Long userId = UserHolder.getUserId();

        //2 判断typ想获取那类型的数据,得到pageREsult ，
        //问题：PagereSult的items存储的是实体类是什么类型好呢？ List<Map>  一个map我会存储两个值：一个userId, score:缘分值
        PageResult pageResult = null;
        switch (type){
            case 1:
                //相互关注
                pageResult = userLikeApi.queryEachLoveList(userId,page,pagesize);
                break;
            case 2:
                //我喜欢
                pageResult = userLikeApi.queryLoveList(userId,page,pagesize);
                break;
            case 3:
                //喜欢我（粉丝）
                pageResult = userLikeApi.queryFansList(userId,page,pagesize);
                break;
            case 4:
                //谁看过我
                pageResult = userLikeApi.queryVisitorsList(userId,page,pagesize);
                break;
        }


        //3. 创建VoList, volist存储UserLikeVo对象
        List<UserLikeVo> voList = new ArrayList<>();
        //4、 遍历pageReuslt的items。 list<Map>，把数据转移到voList
        List<Map<String,Object>> mapList  = (List<Map<String, Object>>) pageResult.getItems();
        if(mapList!=null){
            for (Map<String, Object> map : mapList) {
                UserLikeVo vo = new UserLikeVo();
//                一个map我会存储两个值：一个userId, score:缘分值
                Long uid = (Long) map.get("userId");
                Long score = (Long) map.get("score");
                //查询用户的信息
                UserInfo userInfo = userInfoApi.findById(uid);
                if(userInfo!=null){
                    BeanUtils.copyProperties(userInfo,vo);
                }
                //缘分值
                vo.setMatchRate(score.intValue());
                voList.add(vo);
            }
        }
        pageResult.setItems(voList);

        //5. 返回响应
        return ResponseEntity.ok(pageResult);

    }


    /**
     * 把粉丝添加好友
     * @param fansId
     * @return
     */
    public ResponseEntity fansLike(Long fansId) {
        //1.  得到登陆者id
        Long userId = UserHolder.getUserId();
        //2. 删除粉丝的记录
        userLikeApi.delete(userId,fansId);
        //3. 添加好友
        friendApi.save(userId,fansId.intValue());
        //4. 返回响应
        return ResponseEntity.ok(null);
    }

    public ResponseEntity<Object> updateMobile(User user) {
        userApi.updateMobile(user);
        return ResponseEntity.ok(null);
    }

    public ResponseEntity addLike(Long loveId) {
        Long userId = UserHolder.getUserId();
        //判断是不是我粉丝，是我粉丝就加好友，不是就添加粉丝
        userLikeApi.addLikeUser(userId,loveId);
        return ResponseEntity.ok(true);
    }
}
